package cn.Collection;
import java.util.Objects;
public class ArrayListDemo2 {
        public static void main(String[] args) {
            ArrList<String> list = new ArrList<>(0);
            list.add("a");
            list.add("b");
            list.add("c");
            list.add("d");
            list.add("e");
            list.add("f");
            list.add("g");
            // ArrList<String> list2 = new ArrList<>(0);
            // list2.add(new String("a"));
            // list2.add(new String("b"));
            // list2.add(new String("c"));
            // list2.add(new String("d"));
            // list2.add(new String("e"));
            // list2.add(new String("f"));
            // list2.add(new String("g"));
            // list.add(0, "h");
            // list.add(7, "i");
            // list.indexOf(null);
            // list.remove(0);
            System.out.println(list);
            System.out.println(list.subList(1, 4));
            // System.out.println(list.equals(list2));
        }
    }

    // 模拟：ArrayList
    class ArrList<E> {

        // 定义数组用于存储元素
        private Object[] arr;

        // 定义变量来记录元素的个数
        private int size = 0;

        // 定义变量来记录初始容量
        private int initialCapacity;

        public ArrList() {
            // 初始容量
            arr = new Object[10];
        }

        public ArrList(int initialCapacity) {
            // 判断初始容量的合法性
            if (initialCapacity < 0 || initialCapacity > Integer.MAX_VALUE)
                throw new IllegalArgumentException("非法的容量：" + initialCapacity);
            this.initialCapacity = initialCapacity;
            arr = new Object[initialCapacity];
        }

        // 添加元素
        public void add(E e) {

            // 判断是否需要扩容
            if (size >= arr.length)
                grow();

            // 向size位上来添加元素，同时元素个数+1
            arr[size++] = e;

        }

        // 扩容
        private void grow() {
            Object[] newArr;
            if (arr.length < 2) {
                newArr = new Object[arr.length + 1];
            } else {
                // 构建新数组
                newArr = new Object[arr.length + (arr.length >> 1)];
            }
            // 将原数组的元素拷贝到新数组中
            System.arraycopy(arr, 0, newArr, 0, size);
            // 改变地址
            arr = newArr;
        }

        // 插入元素
        public void add(int index, E e) {
            // 判断下标是否越界
            if (index < 0 || index > size)
                throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
            // 判断是否扩容
            if (size >= arr.length)
                grow();
            // 从指定下标开始，将之后的所有元素后挪一位
            System.arraycopy(arr, index, arr, index + 1, size - index);
            // 将元素放入
            arr[index] = e;
            // 元素个数+1
            size++;
        }

        // 清空集合
        public void clear() {
            // 清空掉数组中原有元素的引用
            for (int i = 0; i < size; i++) {
                arr[i] = null;
            }
            // 将数组回归到初始状态
            arr = new Object[initialCapacity > 0 ? initialCapacity : 10];
            // 元素个数归零
            size = 0;
        }

        // 获取指定元素第一次出现的下标
        public int indexOf(E e) {
            // 遍历数组，来依次比较元素是否与参数相等
            for (int i = 0; i < size; i++) {
                // if (arr[i] == e || arr[i] != null && arr[i].equals(e))
                if (Objects.equals(arr[i], e)) return i;
            }
            // 如果整个循环结束都没有返回，那么说明没有这个元素
            return -1;
        }

        // 判断集合中是否有指定的元素
        public boolean contains(E e) {
            return indexOf(e) != -1;
        }

        // 判断两个列表是否相等
        public boolean equals(Object o) {
            // 判断地址是否相等
            if (this == o) return true;
            // 判断参数是否为空
            if (o == null) return false;
            // 判断参数类型
            if (this.getClass() != o.getClass()) return false;
            // 强转
            ArrList<E> list = (ArrList<E>) o;
            // 判断两个集合中的元素个数
            if (this.size != list.size) return false;
            // 比较两个集合中的元素
            for (int i = 0; i < size; i++) {
                if (!Objects.equals(this.arr[i], list.arr[i])) return false;
            }
            // 整个循环结束都没有返回，那么说明集合中每一个位置上的元素都相等
            return true;
        }

        // 获取指定下标位置上的元素
        public E get(int index) {
            // 判断下标是否越界
            outOfBounds(index);
            return (E) arr[index];
        }

        // 判断越界
        private void outOfBounds(int index) {
            if (index < 0 || index >= size)
                throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
        }

        public int hashCode() {
            int h = 0;
            for (int i = 0; i < size; i++) {
                h = 31 * h + (arr[i] == null ? 0 : arr[i].hashCode());
            }
            return h;
        }

        // 判断集合是否为空
        public boolean isEmpty() {
            return size <= 0;
        }

        // 获取指定元素最后一次出现的下标
        public int lastIndexOf(E e) {
            for (int i = size - 1; i >= 0; i--) {
                if (Objects.equals(arr[i], e)) return i;
            }
            return -1;
        }

        // 移除指定下标位置上的元素
        public void remove(int index) {
            // 判断越界
            outOfBounds(index);
            // 从指定下标的后一位开始，将元素前移
            System.arraycopy(arr, index + 1, arr, index, size - index - 1);
            // 元素个数-1
            size--;
        }

        // 移除指定元素(首次出现)
        public void remove(E e) {
            // 获取这个元素第一次出现的下标
            int index = indexOf(e);
            if (index != -1) remove(index);
        }

        // 替换指定下标位置上的元素
        public void set(int index, E e) {
            outOfBounds(index);
            // 替换
            arr[index] = e;
        }

        // 获取元素个数
        public int size() {
            return size;
        }

        // 截取子列表
        public ArrList<E> subList(int fromIndex, int toIndex) {
            // 判断下标是否合法
            if (fromIndex < 0 || toIndex > size || fromIndex > toIndex)
                throw new IllegalArgumentException();
            // 截取子列表
            ArrList<E> sub = new ArrList<>();
            // 方式一：遍历
        /*
        for (int i = fromIndex; i < toIndex; i++) {
            sub.add((E) arr[i]);
        }
         */
            // 方式二：复制
            int n = toIndex - fromIndex;
            System.arraycopy(arr, fromIndex, sub.arr, 0, n);
            sub.size = n;
            return sub;
        }

        public Object[] toArray(){
            Object[] os = new Object[size];
            System.arraycopy(arr, 0, os, 0, size);
            return os;
        }

        @Override
        public String toString() {
            // 判断集合是否为空
            if (size <= 0) return "[]";
            // 拼接元素
            StringBuilder sb = new StringBuilder("[");
            // 遍历数组
            for (int i = 0; i < size; i++) {
                sb.append(arr[i]).append(", ");
            }
            String str = sb.toString();
            // 截掉最后的", "
            str = str.substring(0, str.length() - 2);
            return str += "]";
        }
}
